home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / timidsrc.zip / wav2pat.c < prev    next >
C/C++ Source or Header  |  1996-05-20  |  8KB  |  345 lines

  1. /*
  2.  
  3.     Wav2pat -- simple WAVE to GUS patch converter
  4.     Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     This is a little tool to convert RIFF WAVEs to GUS-compatible
  21.     patches. A WAVE is read from stdin, and a GUS patch is written to
  22.     stdout.
  23.  
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30.  
  31. #ifdef SOLARIS
  32. #include <string.h>
  33. #else
  34. #include <strings.h>
  35. #endif
  36.  
  37. #include "config.h"
  38. #include "instrum.h"
  39.  
  40. #define DEFAULT_NOTE 60
  41. #define DEFAULT_ROOT 261626
  42.  
  43. int32 freq_table[128]=
  44. {
  45.  8176, 8662, 9177, 9723, 
  46.  10301, 10913, 11562, 12250, 
  47.  12978, 13750, 14568, 15434,
  48.  
  49.  16352, 17324, 18354, 19445,
  50.  20602, 21827, 23125, 24500, 
  51.  25957, 27500, 29135, 30868, 
  52.  
  53.  32703, 34648, 36708, 38891,
  54.  41203, 43654, 46249, 48999,
  55.  51913, 55000, 58270, 61735,
  56.  
  57.  65406, 69296, 73416, 77782,
  58.  82407, 87307, 92499, 97999,
  59.  103826, 110000, 116541, 123471,
  60.  
  61.  130813, 138591, 146832, 155563,
  62.  164814, 174614, 184997, 195998,
  63.  207652, 220000, 233082, 246942,
  64.  
  65.  261626, 277183, 293665, 311127,
  66.  329628, 349228, 369994, 391995,
  67.  415305, 440000, 466164, 493883,
  68.  
  69.  523251, 554365, 587330, 622254,
  70.  659255, 698456, 739989, 783991,
  71.  830609, 880000, 932328, 987767,
  72.  
  73.  1046502, 1108731, 1174659, 1244508,
  74.  1318510, 1396913, 1479978, 1567982,
  75.  1661219, 1760000, 1864655, 1975533,
  76.  
  77.  2093005, 2217461, 2349318, 2489016,
  78.  2637020, 2793826, 2959955, 3135963,
  79.  3322438, 3520000, 3729310, 3951066,
  80.  
  81.  4186009, 4434922, 4698636, 4978032,
  82.  5274041, 5587652, 5919911, 6271927,
  83.  6644875, 7040000, 7458620, 7902133,
  84.  
  85.  8372018, 8869844, 9397273, 9956063, 
  86.  10548082, 11175303, 11839822, 12543854
  87. };
  88.  
  89. int main(int argc, char **argv)
  90. {
  91.   int32
  92.     note=DEFAULT_NOTE,
  93.     root=DEFAULT_ROOT,
  94.     verbosity=0,
  95.     samplerate=-1,
  96.     datasize=-1,
  97.     junklength, c;
  98.  
  99.   int
  100.     infd=STDIN_FILENO;
  101.  
  102.   unsigned char 
  103.     thing[4096],
  104.     *point, 
  105.     modes=0;
  106.  
  107.   while ((c=getopt(argc, argv, "r:n:v"))>0)
  108.     switch(c)
  109.       {
  110.       case 'r': root=atol(optarg); break;
  111.       case 'n': root=freq_table[atoi(optarg) & 127]; break;
  112.       case 'u': note=atol(optarg); break;
  113.       case 'v': verbosity++; break;
  114.       default: return 1;
  115.       }
  116.  
  117.   if (optind==argc-1)
  118.     {
  119.       if ((infd=open(argv[optind], O_RDONLY))<0)
  120.     {
  121.       perror("wav2pat: I can't open your WAVE");
  122.       return 3;
  123.     }
  124.     }
  125.   else if (optind!=argc)
  126.     {
  127.       fprintf(stderr, 
  128.           "Usage: wav2pat [-r RootFreq | -n Note] [-u Note] [-v] [filename]\n");
  129.       return 1;
  130.     }
  131.  
  132.   /* check out the putative RIFF WAVE on stdin */
  133.  
  134.   if (read(infd, thing, 12)<=0)
  135.     {
  136.       perror("wav2pat: I can't read your WAVE");
  137.       return 3;
  138.     }
  139.  
  140.   if (memcmp(thing, "RIFF", 4) || memcmp(thing+8, "WAVE", 4))
  141.     {
  142.       fprintf(stderr, "wav2pat: I want a RIFF WAVE on stdin!\n");
  143.       return 2;
  144.     }
  145.  
  146.   while (datasize==-1)
  147.     {
  148.       if (read(infd, thing, 8)!=8)
  149.     {
  150.       perror("wav2pat: "
  151.          "Your WAVE ran out before I got to the interesting bits");
  152.       return 3;
  153.     }
  154.       junklength=LE_LONG(*((int32 *)(thing+4)));
  155.  
  156.       /* This Microsoft file format is designed to be impossible to
  157.      parse correctly if one doesn't have the full specification.
  158.      If you have a wave with an INFO "chunk", you lose. Thank you
  159.      for playing. */
  160.  
  161.       if (!memcmp(thing, "fmt ", 4))
  162.     {
  163.       if (junklength > 4096)
  164.         {
  165.           fprintf(stderr, "wav2pat: "
  166.               "WAVEs with %ld-byte format blocks make me throw up!\n",
  167.               junklength);
  168.           return 2;
  169.         }
  170.       if (read(infd, thing, junklength) != junklength)
  171.         {
  172.           perror("wav2pat: Your WAVE is mangled");
  173.           return 3;
  174.         }
  175.       if (LE_SHORT(*((int16 *)(thing))) != 1)
  176.         {
  177.           fprintf(stderr, "wav2pat: I don't understand your WAVE. "
  178.               "It has a type %d format chunk!\n",
  179.               LE_SHORT(*((int16 *)(thing))));
  180.           return 2;
  181.         }
  182.       if (LE_SHORT(*((int16 *)(thing + 2))) != 1)
  183.         {
  184.           fprintf(stderr, "wav2pat: This WAVE has %d channels! " 
  185.               "There can be only one!\n",
  186.               LE_SHORT(*((int16 *)(thing + 2))));
  187.           return 2;
  188.         }
  189.       samplerate=LE_LONG(*((int32 *)(thing + 4)));
  190.       switch(LE_SHORT(*((int16 *)(thing + 14))))
  191.         {
  192.         case 8: modes |= MODES_UNSIGNED; break;
  193.         case 16: modes |= MODES_16BIT; break;
  194.         default:
  195.           fprintf(stderr, "wav2pat: Ack! Ppthbth! %d-bit samples!",
  196.               LE_SHORT(*((int16 *)(thing + 14))));
  197.           return 2;
  198.         }
  199.       if (verbosity)
  200.         fprintf(stderr, "wav2pat: This is a %d-bit, %ld Hz WAVE\n",
  201.             (LE_SHORT(*((int16 *)(thing + 14)))),
  202.             samplerate);
  203.     }
  204.       else if (!memcmp(thing, "data", 4))
  205.     {
  206.       if (samplerate==-1)
  207.         {
  208.           fprintf(stderr, "wav2pat: Your WAVE has no format information before data!\n");
  209.           return 2;
  210.         }
  211.       if (verbosity)
  212.         fprintf(stderr, "wav2pat: It has %ld bytes of data\n", junklength);
  213.       datasize=junklength;
  214.     }
  215.       else
  216.     {
  217.       if (verbosity)
  218.         fprintf(stderr, "wav2pat: "
  219.             "Your WAVE has a %ld-byte chunk called `%4.4s'\n",
  220.             junklength, thing);
  221.  
  222.       /* It's cool to pad chunks with NULs to align them on
  223.              half-word boundaries. */
  224.       if (junklength & 1)
  225.         junklength++;
  226.  
  227.       while (junklength>0)
  228.         {
  229.           if ((c=read(infd, thing, (junklength>4096) ? 4096 : junklength)) 
  230.           <= 0)
  231.         {
  232.           perror("wav2pat: Now your WAVE has run out of data");
  233.           return 3;
  234.         }
  235.           junklength -= c;
  236.         }
  237.     }
  238.     }
  239.  
  240.   /* hammer together something that looks like a GUS patch header */
  241.  
  242. #define pound(a) *point++=(a);
  243. #define pounds(a) { *((int16 *)point)=LE_SHORT(a); point+=2; }
  244. #define poundl(a) { *((int32 *)point)=LE_LONG(a); point+=4; }
  245. #define bounce(a) point += a;
  246.   
  247.   memset(thing, 0, 335);
  248.   point=thing;
  249.  
  250.   /* header */
  251.   memcpy(point, "GF1PATCH110", 12);
  252.   point += 12;
  253.  
  254.   /* Gravis ID */
  255.   memcpy(point, "ID#000002", 10);
  256.   point += 10;
  257.   
  258.   /* description */
  259.   strcpy(point, "Copyleft 1995 EWE&U Conductions and one Retreated Gravi\032");
  260.   point += 60;
  261.  
  262.   pound(1); /* instruments */
  263.   pound(14); /* voices */
  264.   pound(0); /* channels */
  265.   pounds(1); /* waveforms */
  266.   pounds(127); /* master volume */
  267.   poundl(datasize); /* data size */
  268.   bounce(36); /* reserved */
  269.  
  270.   pounds(1); /* instrument # */
  271.   strcpy(point, "Bleahnoise"); /* instrument name */
  272.   point += 16;
  273.   poundl(datasize); /* instrument size */
  274.   pound(1); /* layers */
  275.   bounce(40); /* reserved */
  276.  
  277.   pound(0); /* layer duplicate */
  278.   pound(0); /* layer */
  279.   poundl(datasize); /* layer size */
  280.   pound(1); /* samples */
  281.   bounce(40); /* reserved */
  282.   
  283.   strcpy(point, "bleah"); /* wave name */
  284.   point += 7;
  285.   pound(0); /* fractions */
  286.   poundl(datasize); /* wave size */
  287.   poundl(0); /* loop start */
  288.   poundl(datasize); /* loop end */
  289.   pounds(samplerate); /* sample rate */
  290.   poundl(8176); /* low freq */
  291.   poundl(12543854); /* high freq */
  292.   poundl(root); /* root freq */
  293.   pounds(512); /* tune */
  294.   pound(7);  /* balance */
  295.  
  296.   pound(63); /* envelope rates */
  297.   pound(63);
  298.   pound(63);
  299.   pound(63);
  300.   pound(63);
  301.   pound(63);
  302.  
  303.   pound(240); /* envelope offsets */
  304.   pound(240);
  305.   pound(240);
  306.   pound(240);
  307.   pound(240);
  308.   pound(240);
  309.  
  310.   pound(0); /* tremolo sweep */
  311.   pound(0); /* tremolo rate */
  312.   pound(0); /* tremolo depth */
  313.   pound(0); /* vibrato sweep */
  314.   pound(0); /* vibrato rate */
  315.   pound(0); /* vibrato depth */
  316.  
  317.   pound(modes); /* modes */
  318.  
  319.   pounds(note); /* scale freq */
  320.   pounds(1024); /* scale factor */
  321.   bounce(36); /* reserved */
  322.  
  323.   write(STDOUT_FILENO, thing, 335);
  324.  
  325.   /* wave data */
  326.  
  327.   while (datasize>0)
  328.     {
  329.       if ((c=read(infd, thing, (datasize>4096) ? 4096 : datasize)) 
  330.       <= 0)
  331.     {
  332.       perror("wav2pat: I can't read data");
  333.       return 3;
  334.     }
  335.       write(STDOUT_FILENO, thing, c);
  336.       datasize -= c;
  337.     }
  338.  
  339.   /* be courteous */
  340.   if (infd != STDIN_FILENO)
  341.     close(infd);
  342.  
  343.   return 0;
  344. }
  345.